package route
 
import (
	"fmt"
	"reflect"
	. "nightowl/controller"
	"github.com/gin-gonic/gin"
	"strings"
)
//路由结构体
type Route struct {
	path string //url路径
	httpMethod string //http方法 get post
	Method reflect.Value //方法路由
	Args   []reflect.Type //参数类型
}
//路由集合
var Routes =[]Route{}
func InitRouter() *gin.Engine  {
	//初始化路由
	r := gin.Default()
	//绑定基本路由，访问路径：/User/List
	Bind(r)
	return r
}
 
//注册控制器
func Register(restInfo RestInfo, ctrl interface{}) bool{
	// fmt.Print("Register:%+v", ctrl)
	// fmt.Print("path:%s", ctrl.BasePath)
	// ctrlType := reflect.TypeOf(ctrl) 
	// ctrlName := ctrlType.String()
	// module := ctrlName
	// if strings.Contains(ctrlName, ".") {
	// 	module = ctrlName[strings.Index(ctrlName, ".") + 1:]
	// }
	// fmt.Println("module=",module,ctrl)
	v := reflect.ValueOf(ctrl)
	// fmt.Printf("AAAAAA=%+v,%d\n", v,ctrlType.NumMethod(),v.NumMethod())
	//遍历方法

	for i:= 0; i < v.NumMethod(); i++ {


		method := v.Method(i)
		action := v.Type().Method(i).Name
		path := fmt.Sprintf("%s/%s%s", restInfo.BasePath, strings.ToLower(action[0:1]), action[1:])
		// fmt.Println("path:%s\n", path)
		//遍历参数
		params := make([]reflect.Type, 0, v.NumMethod())
		httpMethod :="POST";
		act := strings.ToLower(action)
		getKeys := [...]string{"get","search","start"}
		for _, k := range getKeys{
			if strings.Contains(act, k){
				httpMethod = "GET"
			}
		}
		for j := 0; j < method.Type().NumIn(); j++ {
			params = append(params, method.Type().In(j))
		}
		route := Route{ path:path, Method:method,Args:params,httpMethod:httpMethod}
		Routes =append(Routes,route)
	}
	return true
}
//绑定路由 m是方法GET POST等
//绑定基本路由
func Bind(e *gin.Engine) {
	//pathInit()

	fmt.Println("==========load router start=========")
	for _, route := range Routes {
		//e.POST(path, match(path))
		fmt.Println("Route=",route)
		if(route.httpMethod=="GET"){
			e.GET(route.path,match(route.path,route))
		}
		if(route.httpMethod=="POST"){
			e.POST(route.path,match(route.path,route))
		}
 
	}
	fmt.Println("==========load router end=========")
}
//根据path匹配对应的方法
func match(path string,route Route) gin.HandlerFunc {
	return func(c *gin.Context) {
		fields := strings.Split(path, "/")
		fmt.Println("fields,len(fields)=",fields,len(fields))
		if len(fields) < 3 {
			return
		}
 
		if len(Routes)>0 {
			arguments := make([]reflect.Value, 1)
			arguments[0] = reflect.ValueOf(c) // *gin.Context
			//reflect.ValueOf(method).Method(0).Call(arguments)
			route.Method.Call(arguments)
		}
	}
}